package com.jrx.anytxn.transaction.service.impl;

import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.common.uitl.SeqUtils;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.dto.system.SystemParameterRes;
import com.jrx.anytxn.param.entity.PrInterestTable;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.entity.PrProductTable;
import com.jrx.anytxn.param.entity.PrWaiveInterestTable;
import com.jrx.anytxn.param.service.product.IInterestTableService;
import com.jrx.anytxn.param.service.product.IPrWaiveInterestTableService;
import com.jrx.anytxn.param.service.system.ISystemParameterService;
import com.jrx.anytxn.transaction.bean.LoanParamBean;
import com.jrx.anytxn.transaction.bean.PromotionLabelBean;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.dto.loan.LoanConfirmReq;
import com.jrx.anytxn.transaction.entity.AmLoanMainInfo;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmLoanMainInfoMapper;
import com.jrx.anytxn.transaction.service.ILoanMainInfoService;
import com.jrx.anytxn.transaction.service.IPromotionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 贷款订单service实现
 *
 * @author : zhenghaopu 2019/10/22
 */
@Service
public class LoanMainInfoServiceImpl implements ILoanMainInfoService {

    private static final Logger logger = LoggerFactory.getLogger(LoanMainInfoServiceImpl.class);

    @Resource
    private ExtAmLoanMainInfoMapper extAmLoanMainInfoMapper;
    @Autowired
    private ISegmentService segmentService;
    @Autowired
    private ISystemParameterService systemParameterService;
    @Autowired
    private IInterestTableService interestTableService;
    @Autowired
    private IPrWaiveInterestTableService prWaiveInterestTableService;
    @Autowired
    private IPromotionService promotionService;

    @Override
    public AmLoanMainInfo getAmLoanMainInfoByLoanIdAndCusId(String loanId, String customerId, String tenantId)
            throws TxnBizException {
        AmLoanMainInfo amLoanMainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndCusId(loanId, customerId, tenantId);
        if (amLoanMainInfo == null) {
            logger.error("用户：{}没有订单号：{}的订单", customerId, loanId);
            throw new TxnBizException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getUserTips());
        }
        return amLoanMainInfo;
    }

    @Override
    public AmLoanMainInfo findLoanMainInfoByLoanIdOrContractNumber(String loanId, String contractNumber, String cusId,
                                                                   String tenantId, String channel) throws TxnBizException {
        AmLoanMainInfo amLoanMainInfo = extAmLoanMainInfoMapper.selectAmLoanMainInfoByLoanIdOrContractNumber(loanId,
                contractNumber, cusId, tenantId, channel);
        if (amLoanMainInfo == null) {
            throw new TxnBizException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getUserTips());
        }
        return amLoanMainInfo;
    }

    @Override
    public AmLoanMainInfo buildLoanMainInfo(LoanParamBean loanParamBean, LoanConfirmReq loanConfirmReq,
                                            Date businessDate) throws TxnException {
        // 贷款信息封装
        AmLoanMainInfo amLoanMainInfo = new AmLoanMainInfo();
        try {
            amLoanMainInfo.setId(segmentService.getId(TransBizConstant.AM_LOAN_ID));
        } catch (SegmentException e) {
            logger.error("主键生成错误", e);
            throw new TxnBizException(TxnRespCode.ERROR.getUserTips());
        }
        amLoanMainInfo.setTenantId(loanConfirmReq.getTenantId()); // 租户id
        amLoanMainInfo.setLoanId(
                getLoanId(loanConfirmReq.getTenantId(), loanParamBean.getCustomer().getSecondLevel().getCustomerId()));// 贷款id
        amLoanMainInfo.setOrganizationId(loanParamBean.getChannel().getOrganizationId());// 机构
        amLoanMainInfo.setChannel(loanParamBean.getChannel().getChannelId());// 渠道

        amLoanMainInfo.setProductId(loanParamBean.getProduct().getProductId());// 产品ID
        amLoanMainInfo.setLoanType(loanParamBean.getProduct().getTableType());// 贷款类型
        amLoanMainInfo.setTxnCode(TransBizConstant.TXN_CODE_INSTSUM);// 交易码
        amLoanMainInfo.setCustomerId(loanParamBean.getCustomer().getSecondLevel().getCustomerId());// 客户号
        amLoanMainInfo.setLoanAmount(loanConfirmReq.getLoanAmount());// 贷款金额
        // 获取贷款基础利率
        SystemParameterRes loanPrimeRateRes =
                systemParameterService.findByParamCode(TransBizConstant.LOAN_PRIME_RATE, loanConfirmReq.getTenantId());
        amLoanMainInfo.setLoanPrimeRate(StringUtils.isNotBlank(loanPrimeRateRes.getParamValue())
                ? new BigDecimal(loanPrimeRateRes.getParamValue()) : BigDecimal.ZERO);// LPR贷款基础利率
        amLoanMainInfo.setInterestTableId(loanParamBean.getInterestTableId());// 利率表Id
        amLoanMainInfo.setPayoffTableId(loanParamBean.getPayoffTableId());// 提前结清表ID
        amLoanMainInfo.setFeeTableId(loanParamBean.getFeeTableId());// 费用表ID
        amLoanMainInfo.setPenaltyTableId(loanParamBean.getPenaltyTableId());// 罚息表ID
        amLoanMainInfo.setPaymentSequenceTableId(loanParamBean.getPaymentSequenceTableId());// 还款顺序表ID
        amLoanMainInfo.setPrepayTableId(loanParamBean.getPrePayId());// 提前还款参数
        amLoanMainInfo.setDelqTableId(loanParamBean.getDelqId());// 延滞参数id
        amLoanMainInfo.setTotalTenor(loanConfirmReq.getTenor());

        PrInterestTable interest = loanParamBean.getInterestTable();
        BigDecimal dayRate = interestTableService.getDailyRate(interest, businessDate);// 日利率
        BigDecimal yearRate = interestTableService.getYearRate(interest); // 年利率
        amLoanMainInfo.setActualDailyRate(dayRate);// 日利率
        amLoanMainInfo.setOrigDailyRate(dayRate);// 折扣前利率
        amLoanMainInfo.setInterestRate(yearRate);// 年利率

        PrProductTable prProductTable = loanParamBean.getProduct();
        amLoanMainInfo.setWaiveInterestDays(0);
        if (TransBizConstant.INTEREST_DISCOUNT_FLAG_Y.equals(prProductTable.getInterestDiscountFlag())) {
            PrWaiveInterestTable prWaiveInterestTable = loanParamBean.getPrWaiveInterestTable();
            BigDecimal waiveDayRate = prWaiveInterestTableService.getWaiveDailyRate(prWaiveInterestTable, businessDate);// 日利率
            amLoanMainInfo.setActualWaiveDailyRate(waiveDayRate);
            amLoanMainInfo.setWaiveInterestId(loanParamBean.getWaiveInterestId());
            amLoanMainInfo.setWaiveInterestDays(prProductTable.getWaiveInterestDays());
        }

        amLoanMainInfo.setMerchantId(loanConfirmReq.getMerchantId());
        amLoanMainInfo.setMemoid(StringUtils.isNotBlank(loanConfirmReq.getDescription())
                ? loanConfirmReq.getDescription() : loanParamBean.getProduct().getChineseName());// 备注 若接口上传交易描述为空则取产品名称

        amLoanMainInfo.setBillingCycle(loanConfirmReq.getStatementDay());// 抛账日
        amLoanMainInfo.setPaymentDateDd(loanParamBean.getPaymentDay());// 还款日 先与账单日一样
        amLoanMainInfo.setFirstPaymentDate(loanParamBean.getFirstPaymentDate());
        amLoanMainInfo.setInterestStartDate(loanParamBean.getOrg().getNextProcessingDate());// 交易起息日 当前业务日期
        amLoanMainInfo.setTotalTenor(loanConfirmReq.getTenor()); // 总期数
        amLoanMainInfo
                .setTxnTime(DateUtils.getBusinessTime(new Date(), loanParamBean.getOrg().getNextProcessingDate()));// 交易时间
        // 当前业务日期
        amLoanMainInfo.setPostingDate(loanParamBean.getOrg().getNextProcessingDate()); // 放款时间 当前业务日期
        amLoanMainInfo.setContractId(
                getContractId(loanConfirmReq.getUserId(), loanConfirmReq.getChannel(), loanParamBean.getOrg()));// 合同号
        amLoanMainInfo.setContractNumber(loanConfirmReq.getContractNumber()); // 外部合同号
        amLoanMainInfo.setAmortMethodTableId(loanConfirmReq.getAmortMethod());// 本金摊销方式(还款方式)参数表id
        amLoanMainInfo.setPartnerId(loanParamBean.getProduct().getPartnerId());// 合作方id
        amLoanMainInfo.setSerialNumber(loanConfirmReq.getSeqNo()); // 贷款流水号
        if (null != loanParamBean.getCustomerBank()) {
            amLoanMainInfo.setCustomerAccountNumber(loanParamBean.getCustomerBank().getCardNumber());// 放款配置改造
        }
        amLoanMainInfo.setJointLoanFlag(loanParamBean.getProduct().getAllowJointFlag());// 联合贷标识 0 = 否 1 = 是
        amLoanMainInfo.setRevealMobel(loanParamBean.getProduct().getRevealMobel());// 兜底模式 0 = 我行 1 = 资金源 2 = 合作方 3 = 共享
        amLoanMainInfo.setLoanUse(loanConfirmReq.getLoanUse());

        amLoanMainInfo.setCustRightId(loanConfirmReq.getCustRightId());

        if (StringUtils.isNotBlank(loanParamBean.getWaiveInterestId())) {
            amLoanMainInfo.setWaiveType(TransBizConstant.WAIVE_TYPE_1);
        } else if (null != loanConfirmReq.getCustRightId()) {
            amLoanMainInfo.setWaiveType(TransBizConstant.WAIVE_TYPE_2);
        } else {
            amLoanMainInfo.setWaiveType(TransBizConstant.WAIVE_TYPE_0);
        }

        amLoanMainInfo.setUpdateBy(loanConfirmReq.getUserId());// 更新人
        amLoanMainInfo.setRecordVersionNumber(TransBizConstant.INIT_RECORD_VERSION_NUMBER);
        amLoanMainInfo.setFundId(loanConfirmReq.getFundId()); // 资金源id

        if (amLoanMainInfo.getCustRightId() == null) {
            // 非客户权益 执行促销活动

            PromotionLabelBean promotionLabelBean =
                    promotionService.matchingPromotion(amLoanMainInfo.getTenantId(), amLoanMainInfo.getChannel(),
                            amLoanMainInfo.getCustomerId(), amLoanMainInfo.getProductId(), businessDate);

            if (promotionLabelBean != null) {
                amLoanMainInfo.setLabelCode(promotionLabelBean.getCmCustomerLabel().getLabelCode());
                amLoanMainInfo.setPromotionId(promotionLabelBean.getPrPromotionInfo().getPromotionId());
                // 促销活动贴息
                amLoanMainInfo.setWaiveType(TransBizConstant.WAIVE_TYPE_3);
            }
        }

        // 受托支付
        if (TransBizConstant.YES_FLAG.equals(loanConfirmReq.getEntrustedPayment())) {
            amLoanMainInfo.setCustomerAccountNumber(loanConfirmReq.getCardNumber());
        }

        // 如果上送合同号
        if (StringUtils.isNotBlank(loanConfirmReq.getContractId())) {
            amLoanMainInfo.setContractId(loanConfirmReq.getContractId());
        }
        // 子渠道号
        if (StringUtils.isNotBlank(loanConfirmReq.getSubChannel())) {
            amLoanMainInfo.setSubChannel(loanConfirmReq.getSubChannel());
        }
        // 外部渠道号
        if (StringUtils.isNotBlank(loanConfirmReq.getThirdChannel())) {
            amLoanMainInfo.setThirdChannel(loanConfirmReq.getThirdChannel());
        }
        // 扩展字段
        if (StringUtils.isNotBlank(loanConfirmReq.getExtFields())) {
            amLoanMainInfo.setExtFields(loanConfirmReq.getExtFields());
        }

        return amLoanMainInfo;
    }

    /**
     * 统计 当周 周一至周四 客户 某交易类型总额
     *
     * @param customerId
     * @param loanType
     * @return
     */
    @Override
    public BigDecimal sumByCustomerIdAndLoanTypeFromMondayToThursdayCurrentWeek(String customerId, String loanType,
                                                                                String tenantId, String productId) {
        String monday = DateUtils.getDayOfWeek(Calendar.MONDAY) + " 00:00:00";
        String thursday = DateUtils.getDayOfWeek(Calendar.THURSDAY) + " 23:59:59";
        return extAmLoanMainInfoMapper.sumByCustomerIdAndDateRangeAndLoanType(tenantId, customerId, monday, thursday, loanType
                , productId);
    }

    @Override
    public BigDecimal sumByCustomerIdAndLoanTypeMonthly(String customerId, String loanType, String tenantId, String productId) {
        Date today = new Date();
        String firstDayOfMonth = DateUtils.format(DateUtils.getMonthStartTime(today), DateUtils.DATETIME_PATTERN);
        String endDayOfMonth = DateUtils.format(DateUtils.getMonthEndTime(today), DateUtils.DATETIME_PATTERN);
        return extAmLoanMainInfoMapper.sumByCustomerIdAndDateRangeAndLoanType(tenantId, customerId, firstDayOfMonth,
                endDayOfMonth, loanType, productId);
    }

    /**
     * 统计指定时间区间内消费总额大于指定值的总数（按客户id维度统计）
     *
     * @param tenantId  租户号
     * @param startTime 生效时间
     * @param endTime   失效时间
     * @param loanType  借据类型
     * @param sumAmount 总额值
     * @return
     */
    @Override
    public Integer countDistinctlyGroupByCustomerId(String tenantId, String startTime, String endTime, String loanType,
                                                    BigDecimal sumAmount, String productId) {
        return extAmLoanMainInfoMapper.countDistinctlyGroupByCustomerId(tenantId, startTime, endTime, loanType,
                sumAmount, productId);
    }

    /**
     * 根据租户号、客户号、借据类型查找记录
     *
     * @param tenantId
     * @param customerId
     * @param loanType
     * @return
     */
    @Override
    public List<AmLoanMainInfo> listByCustomerIdAndLoanType(String tenantId, String customerId, String loanType, String productId) {
        return extAmLoanMainInfoMapper.selectByCustomerIdAndLoanType(tenantId, customerId, loanType, productId);
    }

    @Override
    public List<String> getAmLoanMainInfoByConsumeAmountWeekly(String startTime, String endTime, String loanType, BigDecimal sumAmount, String productId) {
        return extAmLoanMainInfoMapper.getAmLoanMainInfoByConsumeAmountWeekly(startTime, endTime, loanType,
                sumAmount, productId);
    }

    /**
     * 获取订单id
     *
     * @param tenantId   租户id
     * @param customerId 客户id
     * @return loanId
     */
    private String getLoanId(String tenantId, String customerId) {
        StringBuilder stringBuilder = new StringBuilder();
        // 取客户后2位
        String customerSuffix = StringUtils.right(customerId, TransBizConstant.LOAN_ID_CUSTOMER_PLACE);
        // accountType(2位)+tenant_id(4位)+customer_id后2位+yyyyMMddHHmmssSSS(17位)+7位随机
        stringBuilder.append(tenantId).append(customerSuffix)
                .append(SeqUtils.getSNByLength(TransBizConstant.LOAN_ID_RANDOM_PLACE));
        return stringBuilder.toString();
    }

    private String getContractId(String userId, String channel, PrOrganizationTable organizationTable)
            throws TxnException {
        SystemParameterRes systemParameterRes =
                systemParameterService.findByParamCode(TransBizConstant.TENANT_NAME_CODE, organizationTable.getTenantId());
        String tenantCode = systemParameterRes.getParamValue();
        StringBuilder stringBuilder = new StringBuilder();
        // CDYH（银行简称缩写）+2位渠道id（从后往前截取）7位userId（从后往前截取）+yyMMddHHmmssSSS+4位协议类型
        stringBuilder.append(tenantCode).append(StringUtils.getLengthStr(channel, 2, '0'))
                .append(StringUtils.getLengthStr(userId, 7, '0'))
                .append(
                        DateUtils.format(DateUtils.getBusinessTime(DateUtils.now(), organizationTable.getNextProcessingDate()),
                                "yyMMddHHmmssSSS"))
                .append(TransBizConstant.LOAN_CONTRACT_TYPE);
        return stringBuilder.toString();
    }

}
